package com.jing.android.notes.ui.thread;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.util.Log;

import com.jing.android.notes.R;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadActivity extends AppCompatActivity {

    private static final String TAG = ThreadActivity.class.getSimpleName();

    private static final int CORE_POOL_SIZE = 1;
    private static final int MAXIMUM_POOL_SIZE = 20;
    private static final int KEEP_ALIVE_SECONDS = 3;

    private ThreadPoolExecutor mExecutor;

    private int id = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        int cpuCount = Runtime.getRuntime().availableProcessors();
        int corePoolSize = Math.max(2, Math.min(cpuCount - 1, 4));

        mExecutor = new ThreadPoolExecutor(
                1, corePoolSize, KEEP_ALIVE_SECONDS,
                TimeUnit.SECONDS, new LinkedBlockingDeque<>(3)) {
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                Log.i(TAG, "before execute: " + r != null ? r.toString() : null);
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                Log.i(TAG, "after execute: " + r != null ? r.toString() : null);
            }
        };
        mExecutor.allowCoreThreadTimeOut(true);
        mExecutor.purge();

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(view -> {
            Log.i(TAG, "Processors: " + Runtime.getRuntime().availableProcessors());
            mExecutor.execute(new Task(id++));
            mExecutor.execute(new Task(id++));
            mExecutor.execute(new Task(id++));
            mExecutor.execute(new Task(id++));
            mExecutor.execute(new Task(id++));
        });
    }

    /**
     *
     */
    class Task implements Runnable {

        private int id;

        Task(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            int count = id + 100;
            for (int i = id; i < count; i++) {
                Log.i(TAG, Thread.currentThread().getName() + " > " + i);
            }
        }

        @Override
        public String toString() {
            return "Task{" +
                    "id=" + id +
                    '}';
        }
    }
}